#include <func.h>
#include "Request.h"
#include "UserInfo.h"
#include "Log.h"
#include "Configuration.h"
#include "Command.h"

#define MAXLINE 2048
#define SPACES " \t\n"

Configuration conf;
UserInfo info;  // 保存用户登录信息

static int tcp_connect(const char* host, const char* service)
{
    struct addrinfo hints, *res, *p;
    // fill out hints
    bzero(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    int rv;
    if ((rv = getaddrinfo(host, service, &hints, &res)) != 0) {
        error(1, 0, "getaddrinfo: %s", gai_strerror(rv));
    }

    // loop through all the results and connect to the first we can
    int sockfd;
    for (p = res; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            error(0, errno, "socket failed");
            continue;
        }
        if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            error(0, errno, "connect failed");
            close(sockfd);
            continue;
        }
        break;
    }
    if (p == NULL) {
        error(1, 0, "connect to %s failed", host);
    }
    freeaddrinfo(res);   // all done with this structure
    printf("Connection established!\n");
    return sockfd;
}

void enable_logging(const char* logfile, const char* loglevel)
{
    if (logfile) {
        log_set_output(logfile);
    } else {
        log_set_output("CloudDisk.log");
    }

    if (loglevel) {
        LogLevel level = LOG_WARN;
        if (strcmp(loglevel, "TRACE") == 0) {
            level = LOG_TRACE;
        } else if (strcmp(loglevel, "DEBUG") == 0) {
            level = LOG_DEBUG;
        } else if (strcmp(loglevel, "INFO") == 0) {
            level = LOG_INFO;
        } else if (strcmp(loglevel, "WARN") == 0) {
            level = LOG_WARN;
        } else if (strcmp(loglevel, "ERROR") == 0) {
            level = LOG_ERROR;
        } else if (strcmp(loglevel, "FATAL") == 0) {
            level = LOG_FATAL;
        }
        log_set_level(level);
    } else {
        log_set_level(LOG_WARN);    // 默认日志级别
    }
}

int main(int argc, char *argv[])
{
    // 读取配置文件
    configuration_init(&conf);
    configuration_load(&conf, "CloudDisk.ini");

    // 开启日志
    const char* logfile = configuration_get(&conf, "LOG_FILE");
    const char* loglevel = configuration_get(&conf, "LOG_LEVEL");
    enable_logging(logfile, loglevel);
    log_trace("test log_trace()");
    log_debug("test log_debug()");
    log_info("test log_info()");
    log_warn("test log_warn()");
    log_error("test log_error()");
    log_fatal("test log_fatal()");

    // 连接服务器
    char* host = configuration_get(&conf, "HOST");
    char* port = configuration_get(&conf, "PORT");
    int connfd = tcp_connect(host, port);
    if (connfd == -1) {
        log_fatal("conect to server failed!");
        exit(1);
    }
    log_info("connect to server success");

    for (;;) {
        if (!info.islogin) {
            login_or_register(connfd, &info);
        } else {
            // 打印用户提示符
            char* cwd = path_str(&info.cwd);
            printf("%s@%s:%s$ ", info.username, host, cwd);
            free(cwd);

            // 读取命令
            char buff[MAXLINE];
            if (fgets(buff, MAXLINE, stdin) == NULL) {
                log_info("close connection\n");
                close(connfd);
                break;
            }

            char* cmd = strtok(buff, SPACES);
            char* params = strtok(NULL, SPACES);

            if (strcmp(cmd, "upload") == 0) {
                upload_file(connfd, params);
            }
        }
    }

    close(connfd);
    configuration_destroy(&conf);
    return 0;
}
